package guggaTests.tasks.containers.taskManager
{
	import flexunit.framework.TestCase;
	import gugga.tasks.containers.taskManager.TaskManager;
	import flexunit.framework.Assert;
	import flash.events.Event;
	import gugga.tasks.FictiveTask;
	import gugga.tasks.events.TaskEvent;
	import gugga.eventHelpers.EventDescriptor;
	import gugga.tasks.CustomCompleteTask;
	import gugga.tasks.ITask;

	public class TaskManagerTest extends TestCase
	{
		private var mIsEventDispatched : Boolean = false;
		
		public function TaskManagerTest(methodName:String=null)
		{
			super(methodName);
		}
		
		public function testConstructor() : void
		{
			var taskManager : TaskManager = new TaskManager();
			assertNotNull(
					"taskManager should not be null after creation", 
					taskManager);
			assertNotUndefined(
					"taskManager should not be undefined after creation", 
					taskManager);
			
			var tasks:Array = taskManager.Tasks;
			assertEquals(
					"tasks should be empty(taskManager still has no TaskManagerItem items)", 
					tasks.length, 
					0);
		}
		
		public function testAddStartingTasks() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
			var eventSource : FictiveTask = new FictiveTask();
			
			var precondition:EventDescriptor = new EventDescriptor(
				eventSource, 
				"start");
			
			fictiveTask.addEventListener(TaskEvent.START, fictiveEventHandler);
			
			/** 
			 * the execution of the following lines will throw exception(the logic 
			 * for addStartingTasks has been changed):
			 * <code>
			 * 	taskManager.addTaskWithPreconditions(fictiveTask, [precondition]);
			 * 	taskManager.addStartingTasks([fictiveTask]);
			 * </code>
			 * but this will work:
			 */
			 
			taskManager.addStartingTasks([fictiveTask]);
			taskManager.addTaskPreconditions(fictiveTask, [precondition]);
			/**
			 * <code>addStartingTasks(aTasks : Array)</code> will create and add 
			 * new <code>TaskManagerItem</code> item to the 
			 * <code>TaskManager</code> and exception will be raised if any of the 
			 * specified tasks is already associated with existing 
			 * <code>TaskManagerItem</code>. It will also add a precondition to 
			 * wait for <b><i>start</i></b> event from the <code>TaskManager</code> 
			 * task, in order to start the <code>TaskManagerItem</code> item's 
			 * execution. The associated <code>TaskManagerItem</code> items will 
			 * start only if the <code>TaskManager</code> task is started, and 
			 * never before it.
			 * 
			 * How to assert this behaviour?
			 * <code>
			 * 	assertThrows(
			 * 			"this task is already added with addStartingTasks", 
			 * 			taskManager.addStartingTasks([fictiveTask]));
			 * </code>
			 */
			
			fictiveTask.addEventListener(TaskEvent.START, fictiveEventHandler);
			assertFalse(
				"Task can't be started before the manager start",
				mIsEventDispatched
				);
			
			taskManager.start();
			
			// taskManager is started, but fictiveTask should not be started yet:
			assertFalse(
				"Task can't be started before the met of the preconditions",
				mIsEventDispatched
				);

			// in order to start fictiveTask the specified precondition should be 
			// met:
			eventSource.start();
		
			// now fictiveTask should be started:
			assertTrue(
				"Task should be started after preconditions are met",
				mIsEventDispatched
				);
			
			mIsEventDispatched = false;
		}
		
		public function testSetStartingTask() : void
		{		
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
			var eventSource : FictiveTask = new FictiveTask();
			
			fictiveTask.addEventListener(TaskEvent.START, fictiveEventHandler);
			
			var precondition:EventDescriptor = new EventDescriptor(
				eventSource, 
				"start");
		
			taskManager.addTaskWithPreconditions(fictiveTask, [precondition]);
			taskManager.setStartingTask(fictiveTask);

			assertFalse(
				"Task can't be started before the manager start",
				mIsEventDispatched
				);
		
			taskManager.start();
			
			// taskManager is started, but fictiveTask should not be started yet
			assertFalse(
				"Task can't be started before the met of the preconditions",
				mIsEventDispatched
				);
				
			eventSource.start();
			
			// now fictiveTask should be started:
			assertTrue(
				"Task should be started after preconditions are met",
				mIsEventDispatched
				);			
		}
		
		public function testStartWithoutFinalPreconditions() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask1 : FictiveTask = new FictiveTask();
			var fictiveTask2 : FictiveTask = new FictiveTask();
			
			fictiveTask2.addEventListener(TaskEvent.START, 
				addAsync(validTestIndicator, 300));

			taskManager.addTaskWithPreconditions(fictiveTask1, []);
			taskManager.addTaskWithPreconditions(fictiveTask2, []);
			
			assertFalse(
				"fictiveTask2 can't be started before the manager start",
				mIsEventDispatched
				);
			
			taskManager.start();
			
			mIsEventDispatched = false;
			
		}
		
		public function testStartWithFinalPreconditions() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask1 : FictiveTask = new FictiveTask();
			var fictiveTask2 : FictiveTask = new FictiveTask();
			
			var finalPrecondition1:EventDescriptor = new EventDescriptor(
				fictiveTask1, 
				"completed");
			var finalPrecondition2:EventDescriptor = new EventDescriptor(
				fictiveTask2,
				"completed");
			
			taskManager.addTaskWithPreconditions(fictiveTask1, []);
			taskManager.addTaskWithPreconditions(fictiveTask2, []);
			
			taskManager.addFinalPreconditions([finalPrecondition1, finalPrecondition2]);	
			
			fictiveTask1.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));			
			fictiveTask2.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			taskManager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			taskManager.start();
		}
		
		public function testInterruptBeforeStart() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
				
			taskManager.addTaskWithPreconditions(fictiveTask, []);
			taskManager.setStartingTask(fictiveTask);
		
			taskManager.addEventListener(TaskEvent.INTERRUPTED, addAsync(validTestIndicator, 300));
	
			fictiveTask.addEventListener(TaskEvent.INTERRUPTED, addAsync(invalidTestIndicator, 300, null,
				validTestIndicator));
	
			taskManager.interrupt();		
		}
		
		public function testInterruptAfterCompleted() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
				
			taskManager.addTaskWithPreconditions(fictiveTask, []);
			taskManager.setStartingTask(fictiveTask);

			taskManager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			taskManager.start();
				
			taskManager.addEventListener(TaskEvent.INTERRUPTED, addAsync(validTestIndicator, 300));	
			
			fictiveTask.addEventListener(TaskEvent.INTERRUPTED, addAsync(invalidTestIndicator, 300, null,
				validTestIndicator));
			
			taskManager.interrupt();

		}

		/**
		 * This test should assure that if we start the <code>TaskManager</code> 
		 * and add a task with precondition which is still not met, the newly added 
		 * task should not get started.
		 */

		public function testAddTaskWithUnmetPreconditionWhenTaskManagerStarted() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
			
			var taskPreconditionTask : CustomCompleteTask = new CustomCompleteTask();
			var taskPrecondition : EventDescriptor = new EventDescriptor(taskPreconditionTask, 
				TaskEvent.COMPLETED);
			
			var managerFinalPreconditionTask : CustomCompleteTask = new CustomCompleteTask();
			var managerFinalPrecondition : EventDescriptor = new EventDescriptor(managerFinalPreconditionTask, 
				TaskEvent.COMPLETED);
			
			taskManager.addFinalPreconditions([managerFinalPrecondition]);
			
			taskManager.addEventListener(TaskEvent.START, fictiveEventHandler)
			
			taskManager.start();
			
			assertTrue(mIsEventDispatched);
			mIsEventDispatched = false;
			
			fictiveTask.addEventListener(TaskEvent.START, addAsync(invalidTestIndicator, 300, 
				null, validTestIndicator));
			taskManager.addTaskWithPrecondition(fictiveTask, taskPrecondition);
			taskPreconditionTask.start();						
		}
		
		public function testAddTaskWithMetPreconditionWhenTaskManagerStarted() : void
		{
			var taskManager : TaskManager = new TaskManager();
			var fictiveTask : FictiveTask = new FictiveTask();
			
			var taskPreconditionTask : CustomCompleteTask = new CustomCompleteTask();
			var taskPrecondition : EventDescriptor = new EventDescriptor(taskPreconditionTask, 
				TaskEvent.COMPLETED);
			
			var managerFinalPreconditionTask : CustomCompleteTask = new CustomCompleteTask();
			var managerFinalPrecondition : EventDescriptor = new EventDescriptor(managerFinalPreconditionTask, 
				TaskEvent.COMPLETED);
			
			taskManager.addFinalPreconditions([managerFinalPrecondition]);
			
			taskManager.addEventListener(TaskEvent.START, fictiveEventHandler)
			
			taskManager.start();
			
			assertTrue(mIsEventDispatched);
			mIsEventDispatched = false;
			
			fictiveTask.addEventListener(TaskEvent.START, addAsync(validTestIndicator, 300));
			taskManager.addTaskWithPrecondition(fictiveTask, taskPrecondition);
			
			taskPreconditionTask.start();
			taskPreconditionTask.complete();
		}
		
		public function testIsRunningAndIsImmediatelyInterruptable() : void
		{
			var taskManager : TaskManager = new TaskManager();
			
			var managerFinalPreconditionTask : CustomCompleteTask = new CustomCompleteTask();
			var managerFinalPrecondition : EventDescriptor = new EventDescriptor(managerFinalPreconditionTask, 
				TaskEvent.COMPLETED);
			
			taskManager.addFinalPreconditions([managerFinalPrecondition]);
			
			assertFalse(
				"Manager is running before start",
				taskManager.isRunning()
				);

			/* its not running and isImmediatelyInterruptable says it is not interruptable 
			 * 
			 * it should say it is immediately interruptable -
			 * whenever you ask the task manager if it is immediately interruptable
			 * it doesn't matter if the interruption is not necessary, 
			 * but it matters that immediately after the interruption call 
			 * the task manager won't be running
			 */
				
			assertTrue(
				"Manager is IsImmediatelyInterruptable while not running",
				taskManager.isImmediatelyInterruptable()
				);
				
			taskManager.start();
			assertTrue(
				"Manager is not running after start and before the finalPrecondition is met",
				taskManager.isRunning()
				);
			
			assertTrue(
				"Manager is IsImmediatelyInterruptable while running becouse there are no not " + 
					"ImmediatelyInterruptable tasks",
				taskManager.isImmediatelyInterruptable()
				);

			managerFinalPreconditionTask.complete();
			assertFalse(
				"Manager is running after the finalPrecondition is met",
				taskManager.isRunning()
				);
				
			assertTrue(
				"Manager is IsImmediatelyInterruptable while not running",
				taskManager.isImmediatelyInterruptable()
				);
		}
			
		/**TODO: implement testIsImmediatelyInterruptableWhenItsNot 
		  and testIsImmediatelyInterruptableWhenItsNotAndNewTasksIsAppendedWhileRunning ()
		 */
		 
		public function testAcceptPrecondition() : void
		{
			var manager : TaskManager = new TaskManager(false);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.acceptPrecondition(finalizationDescriptor);
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
		
			finalilzationTask.start();
		}

		public function testAcceptEventSource() : void
		{
			var manager : TaskManager = new TaskManager(false);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.acceptPrecondition(finalizationDescriptor);
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
		
			finalilzationTask.start();
		}
		
		public function testAll() : void
		{
			var manager : TaskManager = new TaskManager(false);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.acceptAll();
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
		
			finalilzationTask.start();
		}
	
		public function testIgnorePreconditionForFinalPreconditions() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.ignorePrecondition(finalizationDescriptor);
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
		
			finalilzationTask.start();
		}
		
		public function testIgnoreEventSourceForFinalPreconditions() : void
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.ignoreEventSource(finalilzationTask);
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
		
			finalilzationTask.start();	
		}

		public function testIgnoreAllForFinalPreconditions() : void
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, "completed");
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);
			
			manager.ignoreAll();
			
			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
		
			finalilzationTask.start();	
		}

		public function testIgnorePreconditionForTask() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task2PreconditionTask : ITask = new FictiveTask(); 
			
			var task2Precondition : EventDescriptor = new EventDescriptor(
				task2PreconditionTask,
				TaskEvent.COMPLETED
			);
			
			manager.addStartingTask(task1);
			manager.addTaskWithPrecondition(task2, task2Precondition);
			manager.addFinalPreconditions([task2Precondition]);
			manager.ignorePrecondition(task2Precondition);
			
			manager.start();
			
			task2PreconditionTask.start();
			
			assertTrue(
				"manager is not running, but it should be",
				manager.isRunning()
			);
		}
	
		public function testIgnoreEventSourceForTask() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task2PreconditionTask : ITask = new FictiveTask(); 
			
			var task2Precondition : EventDescriptor = new EventDescriptor(
				task2PreconditionTask,
				TaskEvent.COMPLETED
			); 
			
			manager.addStartingTask(task1);
			manager.addTaskWithPrecondition(task2, task2Precondition);
			manager.addFinalPreconditions([task2Precondition]);
			manager.ignoreEventSource(task2PreconditionTask);
			
			manager.start();
			
			task2PreconditionTask.start();
			
			assertTrue(
				"manager is not running, but it should be",
				manager.isRunning()
			);
		}
		
		public function testIgnoreAllForTask() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task2PreconditionTask : ITask = new FictiveTask(); 
			
			var task2Precondition : EventDescriptor = new EventDescriptor(
				task2PreconditionTask,
				TaskEvent.COMPLETED
			); 
			
			manager.addStartingTask(task1);
			manager.addTaskWithPrecondition(task2, task2Precondition);
			manager.addFinalPreconditions([task2Precondition]);
			manager.ignoreAll();
			
			manager.start();
			
			task2PreconditionTask.start();
			
			assertTrue(
				"manager is not running, but it should be",
				manager.isRunning()
			);
		}
	
		public function testAddTaskWithPrecondition() : void
		{	
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			
			var preconditionTask : ITask = new FictiveTask();
			var precondition : EventDescriptor = new EventDescriptor(
				preconditionTask,			
				TaskEvent.START);
		
			var manager : TaskManager = new TaskManager(true);
			
			manager.addStartingTask(task1);
			manager.addTaskWithPrecondition(task2, precondition);
			
			manager.setFinalTask(task2);
			
			task2.addEventListener(TaskEvent.COMPLETED, fictiveEventHandler);
			
			task1.start();
			
			assertTrue(
				"task 1 should be completed",
				mIsEventDispatched
				);
			mIsEventDispatched = false;
		}
		
		public function testAddTaskPrecondition() : void
		{
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			
			var preconditionTask : ITask = new FictiveTask();
			var precondition : EventDescriptor = new EventDescriptor(
				preconditionTask,			
				TaskEvent.COMPLETED
			);
			
			var manager : TaskManager = new TaskManager(true);
			
			manager.addStartingTask(task1);
			manager.addStartingTask(task2);
			
			manager.addTaskPrecondition(task2, precondition);
			manager.setFinalTask(task2);
			
			task2.addEventListener(TaskEvent.START, fictiveEventHandler);
			
			manager.start();
			assertFalse(
				"task2 should not be started before the end of its precondition",
				mIsEventDispatched
				);
			
			preconditionTask.start();
			assertTrue(
				"task2 should be started after the end of its precondition",
				mIsEventDispatched
				);
			
			mIsEventDispatched = false;
		}
		
		public function testRemoveTaskPrecondition() : void
		{
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			
			var preconditionTask : ITask = new FictiveTask();
			var precondition : EventDescriptor = new EventDescriptor(
				preconditionTask,			
				TaskEvent.COMPLETED
			);
			
			var manager : TaskManager = new TaskManager(true);
			
			manager.addStartingTask(task1);
			manager.addStartingTask(task2);
			
			manager.addTaskPrecondition(task2, precondition);
			manager.setFinalTask(task2);
			
			task2.addEventListener(TaskEvent.START, fictiveEventHandler);
			
			manager.start();
			assertFalse(
				"task2 should not be started before the end of its precondition",
				mIsEventDispatched
				);
			
			task2.addEventListener(TaskEvent.START, addAsync(validTestIndicator, 300));
			manager.removeTaskPrecondition(task2, precondition);
			
			mIsEventDispatched = false;
		}
		
		public function testAddFinalPreconditions() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, TaskEvent.COMPLETED);
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);

			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
		}

		public function testAddFinalPreconditionsAfterStart() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();

			var finalilzationTask1 : ITask = new FictiveTask();
			var finalilzationTask2 : ITask = new FictiveTask();
						
			var finalizationDescriptor1 : EventDescriptor = new EventDescriptor(
				finalilzationTask1, TaskEvent.COMPLETED);
				
			var finalizationDescriptor2 : EventDescriptor = new EventDescriptor(
				finalilzationTask2, TaskEvent.COMPLETED);
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor1]);

			manager.start();
			
			manager.addFinalPreconditions([finalizationDescriptor2]);
			finalilzationTask1.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
		}

		public function testRemoveFinalPrecondition() : void 
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, TaskEvent.COMPLETED);
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);

			manager.start();
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			manager.removeFinalPrecondition(finalizationDescriptor);
		}

		public function testRemoveFinalPreconditionBeforeStart() : void
		{
			var manager : TaskManager = new TaskManager(true);
			var task1 : ITask = new FictiveTask();
			var finalilzationTask : ITask = new FictiveTask();
			
			var finalizationDescriptor : EventDescriptor = new EventDescriptor(
				finalilzationTask, TaskEvent.COMPLETED);
				
			manager.addStartingTask(task1);
			manager.addFinalPreconditions([finalizationDescriptor]);

			manager.removeFinalPrecondition(finalizationDescriptor);

			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));

			manager.start();
		}
			
		public function testRemoveTask() : void
		{
			var manager : TaskManager = new TaskManager();
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task3 : ITask = new FictiveTask();
			
			manager.addStartingTask(task1);
			manager.addTaskWithPredecessor(task2, task1);
			manager.addTaskWithPredecessor(task3, task2);
			manager.setFinalTask(task3);
			manager.removeTask(task2);
			
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			task1.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			task3.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			task2.addEventListener(TaskEvent.COMPLETED, addAsync(invalidTestIndicator, 300,
				null, validTestIndicator));
				
			manager.start();
		}

		public function testRemovePredecessorTaskWhileRunning() : void
		{
			var manager : TaskManager = new TaskManager();
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task3 : ITask = new FictiveTask();
			var task4 : ITask = new FictiveTask();
			
			
			var preconditionTask : ITask = new FictiveTask();
			var precondition : EventDescriptor = new EventDescriptor(
				preconditionTask,
				"completed"
			);
			
			// setup manager
			manager.addStartingTask(task1);
			manager.addTaskWithPredecessor(task2, task1);
			manager.addTaskPrecondition(task2, precondition);
			manager.addTaskWithPredecessor(task3, task2);
			manager.addTaskWithPredecessor(task4, task3);
			manager.setFinalTask(task4);
	
			manager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			task1.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			task4.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			manager.start();
			
			manager.removeTask(task3);
				
			preconditionTask.start();	
		}
		
		public function testReplaceTask() : void
		{
			var manager : TaskManager = new TaskManager();
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			var task3 : ITask = new FictiveTask();
			var task4 : ITask = new FictiveTask();
			
			var preconditionTask : ITask = new FictiveTask();
			var precondition : EventDescriptor = new EventDescriptor(
				preconditionTask,
				"completed"
			);
			
			// setup manager
			manager.addStartingTask(task1);
			manager.addTaskWithPredecessor(task2, task1);
			manager.addTaskPrecondition(task2, precondition);
			manager.addTaskWithPredecessor(task3, task2);
			manager.setFinalTask(task3);	
			

			manager.start();	
			manager.replaceTask(task3, task4);	

			task4.addEventListener("start", addAsync(validTestIndicator, 300));
		
			preconditionTask.start()	
		}		

		public function testMarkTask() : void
		{
			var manager : TaskManager = new TaskManager();
			var task1 : ITask = new FictiveTask();
			var task2 : ITask = new FictiveTask();
			
			manager.addStartingTask(task1);
			manager.addTaskWithPredecessor(task2, task1);
			manager.setFinalTask(task2);
			
			manager.markTask(task2, "final");
			
			assertEquals(
				"getMarkedTask(marker) should match the marked task ",
				manager.getMarkedTask("final"),
				task2
			);
			
			assertEquals(
				"getTaskMarker(task) should match the marker",
				manager.getTaskMarker(task2),
				"final"		
			);
		}
		
		public function testCompletionWhenNoFinalPreconditionsSpecified() : void
		{
			var taskManager : TaskManager = new TaskManager(true);
			
			var task1 : CustomCompleteTask = new CustomCompleteTask();
			
			var task2 : CustomCompleteTask = new CustomCompleteTask();
			
			taskManager.addStartingTask(task1);
			taskManager.addTaskWithPredecessor(task2, task1);

			taskManager.addEventListener(TaskEvent.COMPLETED, addAsync(validTestIndicator, 300));
			
			taskManager.start();
		}

		private function validTestIndicator(aEvent : Event, aData : Object = null) : void
		{
			//indicates the test was valid
		}
		
		private function invalidTestIndicator(aEvent : Event, aMessge : String = null) : void
		{
			if(!aMessge)
			{
				aMessge = "Invalid Test";
			}
			
			assertFalse(aMessge, true);
		}
		
		private function fictiveEventHandler(aEvent : Event) : void
		{
			mIsEventDispatched = true;
		}
	}
}